import os

from flask import request, send_file, Blueprint, current_app, Response, stream_with_context
from werkzeug.utils import safe_join

from ...common import helper
from ...common.file import SliceSaveFile, ChunkOptions, get_file_size
from ...extensions import db, sse
from ...models import TransferModel

file_bp = Blueprint('File', __name__, url_prefix='/api')


@file_bp.route("/download", methods=["GET"])
def file_download():
    """

    下载文件

    :return:

    """
    upload_path = current_app.config['UPLOAD_FOLDER']
    uid = request.args["uid"]
    filename = request.args["filename"]
    TransferModel.query.filter_by(id=uid).update(
        {TransferModel.download_count: TransferModel.download_count + 1},
        synchronize_session=False
    )
    db.session.commit()
    target_path = os.path.abspath(safe_join(upload_path, uid, filename))
    return send_file(target_path, as_attachment=True, cache_timeout=0)


def uploaded_stream(uid):
    for i in sse.listen('uploaded'):
        if isinstance(i, sse.Ping):
            yield sse.message('Ping')
        elif isinstance(i, sse.Recycle):
            yield sse.message('Recycle')
        else:
            if i == uid:
                yield sse.message(uid)


@file_bp.route('/file/subscribe/<uid>', methods=['GET'])
def subscribe(uid):
    return Response(stream_with_context(uploaded_stream(uid)), mimetype="text/event-stream")


@file_bp.route('/file/memory', methods=['GET'])
def memory():
    return str(len(sse._event_pool['uploaded']))


def _finished(option: ChunkOptions, result, save_path: str):
    TransferModel.query.filter_by(id=result["uid"]).update({
        "name": option.file_name,
        "size": get_file_size(save_path)
    })
    db.session.commit()
    sse.emit('uploaded', result["uid"])


@file_bp.route("/upload", methods=["POST"])
def file_upload():
    upload_path = current_app.config['UPLOAD_FOLDER']
    options = ChunkOptions.from_flask_request(_finished)

    file = SliceSaveFile(options=options)
    save_folder = safe_join(upload_path, options.file_id)
    if not os.path.exists(save_folder):
        os.mkdir(save_folder)

    file.save_path = safe_join(save_folder, options.file_name)
    data = file.save()

    return helper.success(data=data)


@file_bp.route("/multiple/upload", methods=["POST"])
def multiple_file_upload():
    for file in request.files:
        print(file)
    return helper.success()
